package utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import play.Logger;
import play.modules.redis.RedisConnectionManager;
import redis.clients.jedis.Jedis;

public class RedisUtil {
	private static String province = null;
	private static String password = PropertyUtil.getProperty("redis.password");
	private static String provinces =  PropertyUtil.getProperty("PROVINCES");
	static{
		String provincename = PropertyUtil.getProperty("provincename");
		if(provincename == null){
			throw new RuntimeException("provincename未配置");
		}else{
//			for(Provinces pro : Provinces.values()){
//				if(provincename.trim().equals(pro.toString())){
//					province = pro;
//					break;
//				}
//			}
			province = provincename.trim();
			if(province == null){
				throw new RuntimeException("provincename配置错误，未找到匹配省份");
			}
		}
	}
	public enum RedisDBApp {
	    Station,//车站缓存
	    Organization,//组织机构
	    pricedel,//已删除的班次计划缓存
	    departpassengerdel,//已删除发班运量
	    stationsendmsgtime, //发班运量最大同步时间
	    stationinsurancemsgtime//保险上传接口最大同步时间
	}
	
	public enum Provinces {
		JXS, //江西省
		NMGS,//内蒙
		GSS,//甘肃省
		JLS,//吉林省
		AHS,//安徽省
		HBS,//河北省
		HUBS,//湖北省
		HLJS,//黑龙江
		GST,//甘肃测试
		TJS,//天津市
		NX,//宁夏
		YC,
		JTB,
		HLJT,
		BJS,
		QHS,
		XJS
	}
	
	public static void ChangeDB(String pro, Jedis jedis) 
	{
		try
		{
			if(password != null && !"".equals(password.trim())){
				jedis.auth(password);
			}
			Integer index = getIndexOfProvince(pro);
			if(index==null){
				throw new RuntimeException("provincename配置错误，未找到匹配省份");
			}
			jedis.select(index);
		}	catch (Exception e) {
			e.printStackTrace();
			throw new play.exceptions.UnexpectedException("切换redis数据库出现错误",e);
		}
	}
	
	private static Integer getIndexOfProvince(String provincename) {
		if(provinces !=null && !"".equals(provinces)){
			String[] provincesarr = provinces.split(",");
			int i = 1;
			for(String province : provincesarr){
				if(province.trim().equals(provincename.trim())){
					return i;
				}
				i++;
			}
			return null;
		}else{
			throw new RuntimeException("PROVINCES省份列表未配置");
		}
	}
	
	/**
	 * 向Redis库中添加信息
	 * @param db 库序号
	 * @param key 键
	 * @param value 值
	 * @ldl 重载 无切换redis库的方法
	 */
	public static void set(String key,Object value){
		//key = getKeyHeader() + key;
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		ObjectOutputStream oos;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		try {
			oos = new ObjectOutputStream(baos);
			oos.writeObject(value);
			byte[] buf=baos.toByteArray();
			oos.flush();
			jedis.set(key.getBytes("UTF-8"), buf);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 向Redis库中添加信息
	 * @param db 库序号
	 * @param key 键
	 * @param expiretime 超时时间(单位--分钟)
	 * @param value 值
	 * @ldl 重载 无切换redis库的方法
	 */
	public static void set(String key,Object value,int expiretime){
		//key = getKeyHeader() + key;
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		ObjectOutputStream oos;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		try {
			oos = new ObjectOutputStream(baos);
			oos.writeObject(value);
			byte[] buf=baos.toByteArray();
			oos.flush();
			jedis.setex(key.getBytes("UTF-8"),expiretime*60, buf);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void set(RedisDBApp db,String key,String value){
		//key = getKeyHeader() + key;
		key = db.toString() + key;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		jedis.set(key, value);
		return;
	}
	
	public static void set(RedisDBApp db,String key,String value,int minutes){
		//key = getKeyHeader() + key;
		key = db.toString() + key;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		jedis.setex(key, minutes*60, value);
		
	}
	
	public static void setRemainSecond(RedisDBApp db,String key,String value,int seconds){
		//key = getKeyHeader() + key;
		key = db.toString() + key;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		jedis.setex(key, seconds, value);
		
	}
	
	/**
	 * 向Redis库中添加信息
	 * @param db 库序号
	 * @param key 键
	 * @param value 值
	 */
	public static void set(RedisDBApp db,byte[] key,Object value){
		key = (db.toString() + new String(key, Charset.forName("UTF-8"))).getBytes();
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		ObjectOutputStream oos;
		try {
			oos = new ObjectOutputStream(baos);
			oos.writeObject(value);
			byte[] buf=baos.toByteArray();
			oos.flush();
			Jedis jedis = RedisConnectionManager.getRawConnection();
			ChangeDB(province, jedis);
			jedis.set(key, buf);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 向Redis库中添加信息
	 * @param db 库序号
	 * @param key 键
	 * @param expiretime 超时时间(单位--分钟)
	 * @param value 值
	 */
	public static void set(RedisDBApp db,byte[] key,Object value,int expiretime){
		key = (db.toString() + new String(key, Charset.forName("UTF-8"))).getBytes();
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		ObjectOutputStream oos;
		try {
			oos = new ObjectOutputStream(baos);
			oos.writeObject(value);
			byte[] buf=baos.toByteArray();
			oos.flush();
			Jedis jedis = RedisConnectionManager.getRawConnection();
			ChangeDB(province, jedis);
			jedis.setex(key,expiretime*60, buf);
		} catch (IOException e) {
			Logger.log4j.error("redis set Exception.", e);
		}
	}
	
	
	public static String get(RedisDBApp db,String key){
		//key = getKeyHeader() + key;
		key = db.toString() + key;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		return jedis.get(key);
	}
	/**
	 * 批量插入keys,values
	 * @param db
	 * @param keyvalues
	 */
	public static void set(RedisDBApp db,Map<String,String> keyvalues){
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		List<String> kvlist = new ArrayList<String>();
		for(String key : keyvalues.keySet()){
			kvlist.add(db.toString() + key);
			kvlist.add(keyvalues.get(key));
		}
		if(kvlist.size()>0){
			jedis.mset(kvlist.toArray(new String[kvlist.size()]));
		}
		
	}
	/**
	 * 通过keys,批量获取值
	 * @param db
	 * @param keys
	 * @return
	 */
	public static Map<String,String> get(RedisDBApp db, List<String> keys){
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		String[] keysarr = new String[keys.size()];
		for(int j=0; j<keys.size(); j++){
			keysarr[j] = db.toString()+keys.get(j);
		}
		List<String> values = jedis.mget(keysarr);
		Map<String,String> resultmap = new HashMap<String,String>();
		for(int i=0; i<keys.size(); i++){
			resultmap.put(keys.get(i), values.get(i));
		}
		return resultmap;
	}
	/**
	 * 从Redis库中获得信息
	 * @param db 库序号
	 * @param key 键
	 * @return
	 */
	public static Object get(RedisDBApp db,byte[] key){
		key = (db.toString() + new String(key, Charset.forName("UTF-8"))).getBytes();
		Object objVal=null;
		byte[] value=null;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		value = jedis.get(key);
		if (value!=null) {
			ByteArrayInputStream bais=new ByteArrayInputStream(value);
			try {
				ObjectInputStream ois=new ObjectInputStream(bais);
				objVal=ois.readObject();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		return objVal;
	}
	
	/**
	 * 从Redis库中获得信息
	 * @param db 库序号
	 * @param key 键
	 * @liudl 重载无切换数据库的 获取数据方法
	 * @return
	 */
	public static Object getObject(RedisDBApp db,String key){
		//key = getKeyHeader() + key;
		key = db.toString() + key;
		Object objVal=null;
		byte[] value=null;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		try {
			value = jedis.get(key.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if (value!=null) {
			ByteArrayInputStream bais=new ByteArrayInputStream(value);
			try {
				ObjectInputStream ois=new ObjectInputStream(bais);
				objVal=ois.readObject();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		return objVal;
	}
	
	/**
	 * 从Redis库中删除信息
	 * @param db 库序号
	 * @param key 键
	 */
	public static void delete(RedisDBApp db,String... key){
		for (int i = 0; i < key.length; i++) {
			key[i] = db.toString() + key[i];
		}
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		jedis.del(key);
	}
	/**
	 * 从Redis库中删除信息
	 * @param db 库序号
	 * @param key 键
	 */
	public static void delete(RedisDBApp db,byte[]... key){
		for (int i = 0; i < key.length; i++) {
			key[i] = (db.toString() + new String(key[i], Charset.forName("UTF-8"))).getBytes();
		}
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		jedis.del(key);
	}
	/**
	 * 根据类型获得一组键值对
	 * @param db 库序号
	 * @param type 类型
	 * @return
	 */
	public static Map<String, String> get(RedisDBApp db,int type){
		Map<String, String> map=new HashMap<String, String>();
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		Set<String> keys=jedis.keys(1+"*");
		Iterator<String> keyIter=keys.iterator();
		while (keyIter.hasNext()) {
			String key=keyIter.next();
			String value=RedisConnectionManager.getRawConnection().get(key);
			map.put(key, value);
		}
		return map;
	}
	
	/**
	 * 查询redis中key的剩余时间,单位是秒
	 * @param db
	 * @param key
	 * @return
	 */
	public static Long getRemainTime(RedisDBApp db,String key){
		//key = getKeyHeader() + key;
		key = db.toString() + key;
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		return jedis.ttl(key);
	}
	/**
	 * 查询redis中key的剩余时间,单位为秒
	 * @param db
	 * @param key
	 * @return
	 */
	public static Long getRemainTime(RedisDBApp db,byte[] key){
		key = (db.toString() + new String(key, Charset.forName("UTF-8"))).getBytes();
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		return jedis.ttl(key);
	}
	
	public static void flushdb(Provinces pro) {
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		jedis.flushDB();
	}
	
//	public static String getKeyHeader(){
//		
//		//String mq_from = "datacenter";
//		String mq_from = PropertyUtil.getProperty("mq_from");
//		String keyHeader = "[" + mq_from + "]";
//		return keyHeader;
//	}
//	
	public static Set<String> getAllKeys(RedisDBApp db){
		Jedis jedis = RedisConnectionManager.getRawConnection();
		ChangeDB(province, jedis);
		return jedis.keys(db.toString()+"*");
	}
}
